package com.zhxin.nettylab.nio.chapter3;

import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.ReadTimeoutHandler;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @ClassName ClientTest
 * @Description //客户端
 * @Author singleZhang
 * @Email 405780096@qq.com
 * @Date 2020/12/4 0004 上午 9:52
 **/
public class ClientTest {

    private static Selector selector;

    public static void main(String[] args) throws IOException {



        // 创建通道管理器(Selector)
        selector = Selector.open();

        // 创建通道SocketChannel
        SocketChannel channel = SocketChannel.open();
        // 将通道设置为非阻塞
        channel.configureBlocking(false);

        // 客户端连接服务器，其实方法执行并没有实现连接，需要在handleConnect方法中调channel.finishConnect()才能完成连接
        channel.connect(new InetSocketAddress("localhost", 8989));

        /**
         * 将通道(Channel)注册到通道管理器(Selector)，并为该通道注册selectionKey.OP_CONNECT
         * 注册该事件后，当事件到达的时候，selector.select()会返回，
         * 如果事件没有到达selector.select()会一直阻塞。
         */
        channel.register(selector, SelectionKey.OP_CONNECT);

        while (selector.select() > 0) {

            Set<SelectionKey> selectKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectKeys.iterator();

            while(keyIterator.hasNext()){
                SelectionKey key = keyIterator.next();
                if(key.isConnectable()){
                    // 传输通道连接成功 一般用在客户端
                    handleConnect(key);
                } else if (key.isReadable()) {
                    // 传输通道可读
                    handleRead(key);
                } else if(key.isWritable()) {
                    //传输通道可读
                    handleWrite(key);
                }

                //移除处理完的选择键
                keyIterator.remove();
            }
        }

    }

    /**
     * 处理 和服务器端连接成功事件
     * */
    private static void handleConnect(SelectionKey key) throws IOException {

        // 获取与服务端建立连接的通道
        SocketChannel channel = (SocketChannel) key.channel();
        if (channel.isConnectionPending()) {
            // channel.finishConnect()才能完成连接
            channel.finishConnect();
        }

        channel.configureBlocking(false);

        // 数据写入通道
        String msg = "Hello Server!";
        channel.write(ByteBuffer.wrap(msg.getBytes()));

        // 通道注册到选择器，并且这个通道只对读事件感兴趣
        channel.register(selector, SelectionKey.OP_READ);
    }

    /**
     * 监听到可读，处理服务端发送过来的信息
     */
    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();

        // 从通道读取数据到缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(128);
        channel.read(buffer);

        // 输出服务端响应发送过来的消息
        byte[] data = buffer.array();
        String msg = new String(data).trim();
        System.out.println("client received msg from server：" + msg);
    }

    private static void handleWrite(SelectionKey key){

    }
}
